﻿function AzureOnlineConsoleViewModel(context) {

    var self = this;

    var screen = ko.observable('');

    var requests = context.console.requests;

    var spaRuntime = context.spaRuntime;

    var detailsRoute = spaRuntime.findRouteByName('consoleRequestDetails');
    var createRoute = spaRuntime.findRouteByName('consoleCreateRequest');

    var request = ko.computed(function () {
        var reqs = requests();
        var reqId = context.console.requestId();
        for (var i = 0; i < reqs.length; i++) {
            var req = reqs[i];
            if (req.id == reqId) {
                return req;
            }
        }
        return null;
    });

    spaRuntime.findRouteByName('console').addExecute(function () {
        screen('main');
    });

    detailsRoute.addExecute(function (ev, args) {
        screen('details');
        context.console.requestId(args.requestId);
    });

    createRoute.addExecute(function (ev, args) {
        screen('new');
    });

    function clear() {
        requests.removeAll();
    }


    this.getRequestDetailsUrl = function (request) {
        return detailsRoute.formatHash({
            requestId: request.id
        });
    };

    self.createUrl = function () {
        return createRoute.formatHash({});
    };
    self.newRequest = new AzureOnlineNewRequestView(context);

    self.requests = requests;
    self.request = request;
    self.clear = clear;
    self.screen = screen;
    self.context = context;
}

function AzureOnlineLoggingRecord(request) {
    var uri = request.uri || new Uri();

    var host = uri.getHost();
    var path = uri.getPath();

    var shortHost = host;
    var suffixes = ['table.core.windows.net', 'blob.core.windows.net', 'queue.core.windows.net'];
    for (var i = 0; i < suffixes.length; i++) {
        var suffix = suffixes[i];
        var suffixIndex = host.indexOf(suffix);
        if (suffixIndex >= 0) {
            shortHost = host.substr(0, suffixIndex - 1);
        }
    }

    var url = shortHost + path;

    var headers = [];
    for (var headerName in request.headers) {
        if (headerName) {
            headers.push({
                name: headerName,
                value: request.headers[headerName]
            });
        }
    }

    this.id = 0;
    this.title = request.verb + ' ' + url;
    this.url = url;
    this.path = path;
    this.host = host;
    this.verb = request.verb;
    this.headers = headers;
    this.stringToSign = request.stringToSign;
    this.stringToSignFormatted = request.stringToSign.replace(new RegExp('\n', 'g'), '\\n\n');
    this.status = ko.observable('inprogress');
    this.response = {
        status: ko.observable(''),
        statusText: ko.observable(''),
        headers: ko.observableArray([])
    };
}

function AzureOnlineLoggingChannel(innerChannel) {

    var requests = ko.observableArray([]);

    var id = 1;

    function isValidHeader(name) {
        if (name.indexOf('Content-') == 0) return true;
        if (name.indexOf('x-ms-') == 0) return true;
        if (name == 'Date') return true;
        return false;
    }

    function send(request, success, error, progress) {
        var record = new AzureOnlineLoggingRecord(request);
        record.id = id++;

        requests.unshift(record);

        function processRespones(xhr) {
            record.response.status(xhr.status);
            record.response.statusText(xhr.statusText);
            var headersStr = xhr.getAllResponseHeaders();
            var headersLines = headersStr.split('\r\n');
            for (var i = 0; i < headersLines.length; i++) {
                var line = headersLines[i];
                var colonIndex = line.indexOf(':');
                var name = line.substr(0, colonIndex);

                if (name && isValidHeader(name)) {
                    record.response.headers.push({
                        name: name,
                        value: line.substr(colonIndex + 1).replace(/^\s\s*/, '').replace(/\s\s*$/, '')
                    });
                }
            }
        }

        innerChannel.send.apply(innerChannel, [request, function (data, xhr) {
            record.status('complete');
            processRespones(xhr);
            if (success) success(data, xhr);
        }, function (data, xhr) {
            processRespones(xhr);
            record.status('error');
            if (error) error(data, xhr, record);
        }, progress]);
    }

    this.send = send;
    this.getDownloadUrl = innerChannel.getDownloadUrl;
    this.requests = requests;
}

(function () {

    function setStatus(element, value) {
        var $element = $(element);
        $element.removeClass('request-inprogress');
        $element.removeClass('request-complete');
        $element.removeClass('request-error');
        $element.addClass('request-' + value);
    }

    ko.bindingHandlers.requestStatus = {
        init: function (element, valueAccessor) {
            var data = valueAccessor();
            var status = ko.utils.unwrapObservable(data);
            setStatus(element, status);
        },
        update: function (element, valueAccessor) {
            var data = valueAccessor();
            var status = ko.utils.unwrapObservable(data);
            setStatus(element, status);
        }

    };

})();


$.fn.consolePanel = function () {
    function init($this) {

        var visible = false;

        function show() {
            visible = true;
            $this.stop();
            $this.show();
            $this.animate({
                height: '80%'
            });
        }

        function hide() {
            visible = false;
            $this.stop();
            $this.animate({
                height: '0%'
            });
        }

        function toggle() {
            if (visible) {
                hide();
            } else {
                show();
            }
        }

        return {
            show: show,
            hide: hide,
            toggle: toggle
        };
    }

    var data = this.data('consolePanel');
    if (!data) {
        data = init($(this));
        this.data('consolePanel', data);
    }

    return data;
};

ko.bindingHandlers.consolePanel = {
    init: function (element) {
        var panel = $(element).consolePanel();
    }
};

ko.bindingHandlers.consolePanelSwitch = {
    init: function (element, valueAccessor) {
        var $element = $(element);
        $element.bind('click', function () {
            var eid = ko.utils.unwrapObservable(valueAccessor());
            var $panel = $('#' + eid).consolePanel();
            $panel.toggle();
        });
    }
};

(function () {

    $(document).ready(function () {
        $('body').keydown(function (e) {
            var $panel = $('#console-panel').consolePanel();

            var ctrlDown = e.ctrlKey || e.metaKey;
            var c = e.keyCode;
            if (ctrlDown && c == 192) {
                $panel.toggle();
            }
            return true;

        });
    });


})();
